##########################################################################################
# Title: City Boundaries → Native (WGS84) + Projected (Mollweide) GPKGs
# Section: 2 (Inputs)
# Purpose: Standardize admin boundaries for 25 cities (native + projected)
# IO:
#   IN:  Data/Shape_Files/gadm41_XXX_{1,2}.shp
#   OUT: Processed_Data/City_Boundaries/<City>_n.gpkg (native), <City>.gpkg (Mollweide)
##########################################################################################

rm(list = ls()); options(stringsAsFactors = FALSE)

suppressPackageStartupMessages({
  library(sf)
  library(dplyr)
})

# ---- Project root (align with run_all.R) -------------------------------------
if (!requireNamespace("here", quietly = TRUE)) install.packages("here", quiet = TRUE)
ROOT    <- normalizePath(here::here(), winslash = "/")
DATA_SD <- file.path(ROOT, "Data", "Shape_Files")
OUT_DIR <- file.path(ROOT, "Processed_Data", "City_Boundaries")
dir.create(OUT_DIR, recursive = TRUE, showWarnings = FALSE)

# ---- CRSs --------------------------------------------------------------------
CRS_WGS84 <- sf::st_crs(4326)
CRS_MOLL  <- sf::st_crs("+proj=moll +lon_0=0 +datum=WGS84 +units=m +no_defs")  # ESRI:54009 equivalent

# ---- Robust make-valid (portable across environments) ------------------------
safe_make_valid <- function(x) {
  if ("st_make_valid" %in% getNamespaceExports("sf")) {
    return(sf::st_make_valid(x))
  }
  if (requireNamespace("lwgeom", quietly = TRUE) &&
      "st_make_valid" %in% getNamespaceExports("lwgeom")) {
    return(lwgeom::st_make_valid(x))
  }
  warning("st_make_valid not available; using st_buffer(., 0) fallback")
  sf::st_buffer(x, 0)
}

# ---- Helper ------------------------------------------------------------------
write_city <- function(v_native, predicate, out_stem) {
  x_nat <- v_native %>% dplyr::filter({{ predicate }})
  if (nrow(x_nat) == 0) stop("No features matched for: ", out_stem)
  
  # Ensure valid geometries (portable)
  x_nat <- safe_make_valid(x_nat)
  
  # Force native to WGS84 if needed
  if (is.na(sf::st_crs(x_nat))) sf::st_crs(x_nat) <- CRS_WGS84
  if (sf::st_crs(x_nat) != CRS_WGS84) x_nat <- sf::st_transform(x_nat, CRS_WGS84)
  
  # Write native (WGS84)
  sf::st_write(x_nat, file.path(OUT_DIR, paste0(out_stem, "_n.gpkg")), delete_dsn = TRUE, quiet = TRUE)
  
  # Project to Mollweide and write
  x_moll <- sf::st_transform(x_nat, CRS_MOLL)
  sf::st_write(x_moll, file.path(OUT_DIR, paste0(out_stem, ".gpkg")), delete_dsn = TRUE, quiet = TRUE)
}

# ============================= LOAD SOURCES ===================================

# South Africa (level 2)
za2 <- sf::st_read(file.path(DATA_SD, "gadm41_ZAF_2.shp"), quiet = TRUE)

# USA (level 2)
usa2 <- sf::st_read(file.path(DATA_SD, "gadm41_USA_2.shp"), quiet = TRUE)

# Kenya (level 1)
ken1 <- sf::st_read(file.path(DATA_SD, "gadm41_KEN_1.shp"), quiet = TRUE)

# Nigeria (level 1)
nga1 <- sf::st_read(file.path(DATA_SD, "gadm41_NGA_1.shp"), quiet = TRUE)

# Côte d’Ivoire (level 1)
civ1 <- sf::st_read(file.path(DATA_SD, "gadm41_CIV_1.shp"), quiet = TRUE)

# Egypt (level 1)
egy1 <- sf::st_read(file.path(DATA_SD, "gadm41_EGY_1.shp"), quiet = TRUE)

# United Kingdom (level 2)
gbr2 <- sf::st_read(file.path(DATA_SD, "gadm41_GBR_2.shp"), quiet = TRUE)

# Turkey (level 1)
tur1 <- sf::st_read(file.path(DATA_SD, "gadm41_TUR_1.shp"), quiet = TRUE)

# South Korea (level 1)
kor1 <- sf::st_read(file.path(DATA_SD, "gadm41_KOR_1.shp"), quiet = TRUE)

# Brazil (level 2)
bra2 <- sf::st_read(file.path(DATA_SD, "gadm41_BRA_2.shp"), quiet = TRUE)

# China (level 2)
chn2 <- sf::st_read(file.path(DATA_SD, "gadm41_CHN_2.shp"), quiet = TRUE)

# India (level 2)
ind2 <- sf::st_read(file.path(DATA_SD, "gadm41_IND_2.shp"), quiet = TRUE)

# Malaysia (level 1)
mys1 <- sf::st_read(file.path(DATA_SD, "gadm41_MYS_1.shp"), quiet = TRUE)

# Russia (level 1)
rus1 <- sf::st_read(file.path(DATA_SD, "gadm41_RUS_1.shp"), quiet = TRUE)

# Mexico (level 1)
mex1 <- sf::st_read(file.path(DATA_SD, "gadm41_MEX_1.shp"), quiet = TRUE)

# Argentina (level 1)
arg1 <- sf::st_read(file.path(DATA_SD, "gadm41_ARG_1.shp"), quiet = TRUE)

# Iran (level 1)
irn1 <- sf::st_read(file.path(DATA_SD, "gadm41_IRN_1.shp"), quiet = TRUE)

# UAE (level 1)
are1 <- sf::st_read(file.path(DATA_SD, "gadm41_ARE_1.shp"), quiet = TRUE)

# Germany (level 2)
deu2 <- sf::st_read(file.path(DATA_SD, "gadm41_DEU_2.shp"), quiet = TRUE)

# Switzerland (level 1)
che1 <- sf::st_read(file.path(DATA_SD, "gadm41_CHE_1.shp"), quiet = TRUE)

# Colombia (level 1)
col1 <- sf::st_read(file.path(DATA_SD, "gadm41_COL_1.shp"), quiet = TRUE)

# ============================= WRITE CITIES ===================================

# SOUTH AFRICA (Level 2)
write_city(za2, NAME_2 == "City of Johannesburg", "Johannesburg")
write_city(za2, NAME_2 == "City of Cape Town",    "Capetown")
write_city(za2, NAME_2 == "City of Tshwane",      "Tshwane")
write_city(za2, NAME_2 == "eThekwini",            "Durban")
write_city(za2, NAME_2 == "Nelson Mandela Bay",   "NM_Bay")

# USA (NYC five counties)
usa2_ny <- usa2 %>% dplyr::filter(NAME_1 == "New York")
write_city(usa2_ny, NAME_2 %in% c("New York","Kings","Queens","Bronx","Richmond"), "New_York")

# KENYA
write_city(ken1, NAME_1 == "Nairobi", "Nairobi")

# NIGERIA
write_city(nga1, NAME_1 == "Lagos", "Lagos")

# CÔTE D’IVOIRE
write_city(civ1, NAME_1 == "Abidjan", "Abidjan")

# EGYPT
write_city(egy1, NAME_1 == "Al Qahirah", "Cairo")

# UNITED KINGDOM (Greater London)
write_city(gbr2, GID_2 == "GBR.1.36_1", "London")

# TURKEY
write_city(tur1, NAME_1 == "Istanbul", "Istanbul")

# SOUTH KOREA
write_city(kor1, NAME_1 == "Seoul", "Seoul")

# BRAZIL  (accent in GADM)
write_city(bra2, NAME_2 == "São Paulo", "SaoPaulo")

# CHINA
write_city(chn2, NAME_2 == "Shenzhen", "Shenzhen")

# INDIA
write_city(ind2, NAME_2 == "Mumbai City", "Mumbai")

# MALAYSIA
write_city(mys1, NAME_1 == "Kuala Lumpur", "KualaLumpur")

# RUSSIA
write_city(rus1, NAME_1 == "Moscow City", "Moscow")

# MEXICO
write_city(mex1, NAME_1 == "Distrito Federal", "Mexico_City")

# ARGENTINA
write_city(arg1, NAME_1 == "Ciudad de Buenos Aires", "Buenos_Aires")

# IRAN
write_city(irn1, NAME_1 == "Tehran", "Tehran")

# UAE
write_city(are1, NAME_1 == "Dubai", "Dubai")

# GERMANY
write_city(deu2, NAME_2 == "Frankfurt am Main", "Frankfurt")

# SWITZERLAND
write_city(che1, GID_1 == "CHE.26_1", "Zurich")

# COLOMBIA
write_city(col1, GID_1 == "COL.5_2", "Bogota")




